package org.benjamin.lending.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.benjamin.lending.domain.entity.TransactRequest;
import org.benjamin.lending.domain.transact.TransactBean;
import org.benjamin.lending.repository.TransactRequestRepository;
import org.benjamin.lending.service.TransactService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.util.WebUtils;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("transact")
public class TransactController {

	private Logger logger = LogManager.getLogger();

	@Autowired
	private EhCacheCacheManager ehCacheCacheManager;

	@Autowired
	private TransactRequestRepository transactRequestRepository;

	@Autowired
	private TransactService transactService;

	@RequestMapping("request/{id}")
	public ModelAndView request(@PathVariable("id") String id)
			throws JsonParseException, JsonMappingException, IOException {
		ModelAndView modelAndView = new ModelAndView("transact/request");
		Cache cache = this.ehCacheCacheManager.getCache("org.lending");
		TransactBean transactBean = cache.get(id, TransactBean.class);
		if (transactBean == null) {
			logger.info("transactBean对象无法在缓存找到，将在数据库中查询并合并新的transactBean对象");
			transactBean = new TransactBean();
			TransactRequest transactRequest = this.transactRequestRepository.findOne(id);
			transactBean.setTargetUrl(transactRequest.getTargetUrl());
			Map<String, Object> paramterMap = new ObjectMapper().readValue(transactRequest.getPackData(),
					HashMap.class);
			transactBean.setParamterMap(paramterMap);
			logger.debug("组装参数有Url：{}，Key-Value参数是：{}", transactBean.getTargetUrl(), transactBean.getParamterMap());
			logger.info("transactBean从新组装完毕");
			cache.put(id, transactBean);
		} else {
			logger.info("成功的从缓存中取出对象");
		}
		modelAndView.addObject("transactBean", transactBean);
		return modelAndView;
	}

	@ResponseBody
	@RequestMapping("response")
	public String response(HttpServletRequest request) {
		Map<String, Object> responseMap = WebUtils.getParametersStartingWith(request, "");
		String requestId = responseMap.get("requestId").toString();
		return this.responseById(requestId, request);
	}

	@ResponseBody
	@RequestMapping("response/{requestId}")
	public String responseById(@PathVariable("requestId") String requestId, HttpServletRequest request) {
		logger.info("响应操作");
		try {
			Map<String, Object> responseMap = WebUtils.getParametersStartingWith(request, "");
			TransactRequest transactRequest = this.transactRequestRepository.findOne(requestId);
			try {
				String resultDate = new ObjectMapper().writeValueAsString(responseMap);
				transactRequest.setResultData(resultDate);
			} catch (Exception e) {
				logger.warn("解析异常：{}", responseMap);
			}
			switch (transactRequest.getType()) {
			case REGISTER_USER:
				this.transactService.registerAccountResponse(transactRequest, responseMap);
				break;
			case RECHARGE:
				// 充值响应
				this.transactService.userRechargeResponse(transactRequest, responseMap);
				logger.info("充值响应任务完成");
				break;
			case WITHDRAW:
				this.transactService.withdrawResponse(transactRequest, responseMap);
				break;
			default:
				logger.warn("不存在什么默认");
			}
		}catch(Exception e) {
			logger.error(e.getMessage(),e);
			return "faile";
		}
		return "success";
	}

}
